#include <Timer.h>
namespace timer
{

    Timer::Timer(std::string name,
                 std::chrono::steady_clock::time_point startTime,
                 std::chrono::nanoseconds lastTime,
                 std::chrono::seconds delayTime,
                 ENUM_TIMER_TYPE timertype,
                 Callback &&callback)
        : mTimerName(std::move(name)),
          mCallback(std::move(callback)),
          mStartTime(startTime),
          mLastTime(lastTime),
          mDelayTime(delayTime),
          mTimerType(timertype)
    {
    }

    const std::chrono::steady_clock::time_point &
    Timer::getStartTime() const
    {
        return mStartTime;
    }

    const std::chrono::nanoseconds &
    Timer::getLastTime() const
    {
        return mLastTime;
    }
    std::string Timer::getName()
    {
        return mTimerName;
    }
    std::chrono::nanoseconds Timer::getLeftTime()
    {
        const auto now = std::chrono::steady_clock::now();
        auto delayTime = mDelayTime;
        mDelayTime = std::chrono::seconds(0);
        return getLastTime() - (now - getStartTime()) + delayTime;
    }

    void Timer::cancel()
    {
        std::call_once(mExecuteOnceFlag, [this]()
                       { mCallback = nullptr; });
    }

    ENUM_TIMER_TYPE Timer::get_timer_type()
    {
        return mTimerType;
    }

    void Timer::operator()()
    {
        if (mTimerType == ENUM_TIMER_TYPE::TIMER_TYPE_ONCE)
        {
            Callback callback;
            std::call_once(mExecuteOnceFlag, [&callback, this]()
                           {
                               callback = std::move(mCallback);
                               mCallback = nullptr; });

            if (callback != nullptr)
            {
                callback();
            }
        }
        else
        {
            if (mCallback != nullptr)
            {
                mCallback();
            }
            mStartTime = std::chrono::steady_clock::now();
        }
    }
}